package com.hww.common.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Build;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.CheckResult;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;


/**
 * This file is part of Toasty.
 * <p>
 * Toasty is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <p>
 * Toasty is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <p>
 * You should have received a copy of the GNU General Public License
 * along with Toasty.  If not, see <http://www.gnu.org/licenses/>.
 */

@SuppressLint("InflateParams")
public class ToastUtils {
    private static final Typeface LOADED_TOAST_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
    private static Typeface currentTypeface = LOADED_TOAST_TYPEFACE;
    private static int textSize = 16; // in SP

    private static boolean tintIcon = true;
    private static boolean allowQueue = true;
    private static int toastGravity = -1;
    private static int xOffset = -1;
    private static int yOffset = -1;
    private static boolean supportDarkTheme = true;
    private static boolean isRTL = false;

    private static Toast lastToast = null;

    public static final int LENGTH_SHORT = Toast.LENGTH_SHORT;
    public static final int LENGTH_LONG = Toast.LENGTH_LONG;

    private ToastUtils() {
        // avoiding instantiation
    }

    /**
     * 创建一个具有普通样式的Toast。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @StringRes int message) {
        return normal(context, context.getString(message), Toast.LENGTH_SHORT, null, false);
    }

    /**
     * 创建一个具有普通样式的Toast。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @NonNull CharSequence message) {
        return normal(context, message, Toast.LENGTH_SHORT, null, false);
    }

    /**
     * 创建一个具有普通样式的Toast。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @StringRes int message, Drawable icon) {
        return normal(context, context.getString(message), Toast.LENGTH_SHORT, icon, true);
    }

    /**
     * 创建一个具有普通样式的Toast。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @NonNull CharSequence message, Drawable icon) {
        return normal(context, message, Toast.LENGTH_SHORT, icon, true);
    }

    /**
     * 创建一个具有普通样式的Toast。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @StringRes int message, int duration) {
        return normal(context, context.getString(message), duration, null, false);
    }

    /**
     * 创建一个具有普通样式的Toast。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @NonNull CharSequence message, int duration) {
        return normal(context, message, duration, null, false);
    }

    /**
     * 创建一个具有普通样式的Toast。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @StringRes int message, int duration,
                               Drawable icon) {
        return normal(context, context.getString(message), duration, icon, true);
    }

    /**
     * 创建一个具有普通样式的Toast。
     * 这个方法提供了一个简便的方式來创建一个显示消息的Toast，同时支持选择是否显示图标。
     *
     * @param context  上下文对象，用于显示Toast。
     * @param message  要显示的消息内容。
     * @param duration Toast显示的时长，可以是短时长（Toast.LENGTH_SHORT）或长时长（Toast.LENGTH_LONG）。
     * @param icon     要显示的图标，如果不需要显示图标，可以传入null。
     * @return 返回创建的Toast对象，可以通过此对象进一步配置或直接显示。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @NonNull CharSequence message, int duration,
                               Drawable icon) {
        return normal(context, message, duration, icon, true);
    }

    @CheckResult
    public static Toast normal(@NonNull Context context, @StringRes int message, int duration,
                               Drawable icon, boolean withIcon) {
        return normalWithDarkThemeSupport(context, context.getString(message), icon, duration, withIcon);
    }

    /**
     * 创建一个具有普通样式的Toast。
     * 这个方法提供了一个简便的方式來创建一个显示消息的Toast，同时支持选择是否显示图标。
     *
     * @param context  上下文对象，用于显示Toast。
     * @param message  要显示的消息内容。
     * @param duration Toast显示的时长，可以是短时长（Toast.LENGTH_SHORT）或长时长（Toast.LENGTH_LONG）。
     * @param icon     要显示的图标，如果不需要显示图标，可以传入null。
     * @param withIcon 指示是否应该显示图标的布尔值，如果为true，则显示图标；如果为false，则不显示。
     * @return 返回创建的Toast对象，可以通过此对象进一步配置或直接显示。
     */
    @CheckResult
    public static Toast normal(@NonNull Context context, @NonNull CharSequence message, int duration,
                               Drawable icon, boolean withIcon) {
        return normalWithDarkThemeSupport(context, message, icon, duration, withIcon);
    }

    /**
     * 显示一个自定义的警告类型Toast。
     */
    @CheckResult
    public static Toast warning(@NonNull Context context, @StringRes int message) {
        return warning(context, context.getString(message), Toast.LENGTH_SHORT, true);
    }

    /**
     * 显示一个自定义的警告类型Toast
     */
    @CheckResult
    public static Toast warning(@NonNull Context context, @NonNull CharSequence message) {
        return warning(context, message, Toast.LENGTH_SHORT, true);
    }

    /**
     * 显示一个自定义的警告类型Toast。
     */
    @CheckResult
    public static Toast warning(@NonNull Context context, @StringRes int message, int duration) {
        return warning(context, context.getString(message), duration, true);
    }

    /**
     * 显示一个自定义的警告类型Toast。
     */
    @CheckResult
    public static Toast warning(@NonNull Context context, @NonNull CharSequence message, int duration) {
        return warning(context, message, duration, true);
    }

    /**
     * 显示一个自定义的警告类型Toast。
     *
     * @param context  Toast显示的上下文环境，不能为空。
     * @param message  Toast显示的文本内容，从资源文件中获取，不能为空。
     * @param duration Toast显示的时长，可以是短时长（Toast.LENGTH_SHORT）或长时长（Toast.LENGTH_LONG）。
     * @param withIcon 指示是否在Toast中显示图标。
     * @return 返回定制的Toast对象，可用于进一步的定制或显示。
     */
    @CheckResult
    public static Toast warning(@NonNull Context context, @StringRes int message, int duration, boolean withIcon) {
        return custom(context, context.getString(message), getDrawable(context, com.hww.common.R.drawable.ic_error_outline_white_24dp),
                getColor(context, com.hww.common.R.color.warningColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 显示一个自定义的警告类型Toast。
     *
     * @param context  上下文对象，用于显示Toast。
     * @param message  要显示的Toast消息内容。
     * @param duration Toast显示的时长，可以是短时长（Toast.LENGTH_SHORT）或长时长（Toast.LENGTH_LONG）。
     * @param withIcon 是否在Toast中显示图标。
     * @return 返回定制的Toast对象。
     */
    @CheckResult
    public static Toast warning(@NonNull Context context, @NonNull CharSequence message, int duration, boolean withIcon) {
        return custom(context, message, getDrawable(context, com.hww.common.R.drawable.ic_error_outline_white_24dp),
                getColor(context, com.hww.common.R.color.warningColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 显示一个带有信息图标的Toast提示。
     */
    @CheckResult
    public static Toast info(@NonNull Context context, @StringRes int message) {
        return info(context, context.getString(message), Toast.LENGTH_SHORT, true);
    }

    /**
     * 显示一个带有信息图标的Toast提示。
     */
    @CheckResult
    public static Toast info(@NonNull Context context, @NonNull CharSequence message) {
        return info(context, message, Toast.LENGTH_SHORT, true);
    }

    /**
     * 显示一个带有信息图标的Toast提示。
     */
    @CheckResult
    public static Toast info(@NonNull Context context, @StringRes int message, int duration) {
        return info(context, context.getString(message), duration, true);
    }

    /**
     * 显示一个带有信息图标的Toast提示。
     */
    @CheckResult
    public static Toast info(@NonNull Context context, @NonNull CharSequence message, int duration) {
        return info(context, message, duration, true);
    }

    /**
     * 显示一个带有信息图标的Toast提示。
     * <p>
     * 此方法为调用者提供了显示一个具有特定样式的信息提示的便利方法。它通过传入的上下文、消息内容、持续时间以及是否显示图标来创建并显示一个Toast。
     * 默认情况下，该方法使用预定义的信息图标、信息提示的颜色、文本颜色以及指定的持续时间来展示Toast。
     * </p>
     *
     * @param context  Toast显示的上下文，不能为空。
     * @param message  Toast显示的消息内容，从资源文件中获取，不能为空。
     * @param duration Toast的显示持续时间，可以是短时间（Toast.LENGTH_SHORT）或长时间（Toast.LENGTH_LONG）。
     * @param withIcon 指示是否在Toast中显示图标。
     * @return 返回创建的Toast实例，可以进一步定制或立即显示。
     */
    @CheckResult
    public static Toast info(@NonNull Context context, @StringRes int message, int duration, boolean withIcon) {
        return custom(context, context.getString(message), getDrawable(context, com.hww.common.R.drawable.ic_info_outline_white_24dp),
                getColor(context, com.hww.common.R.color.infoColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 显示一个带有信息图标的Toast提示。
     * <p>
     * 此方法为调用者提供了显示一个具有特定样式的信息提示的便利方法。它通过传入的上下文、消息内容、持续时间以及是否显示图标来创建并显示一个Toast。
     * 默认情况下，该方法使用预定义的信息图标、信息提示的颜色、文本颜色以及指定的持续时间来展示Toast。
     * </p>
     *
     * @param context  Toast显示的上下文，不能为空。
     * @param message  Toast显示的消息内容，不能为空。
     * @param duration Toast的显示持续时间，可以是短时间（Toast.LENGTH_SHORT）或长时间（Toast.LENGTH_LONG）。
     * @param withIcon 指示是否在Toast中显示图标。
     * @return 返回创建的Toast实例，可以进一步定制或立即显示。
     */
    @CheckResult
    public static Toast info(@NonNull Context context, @NonNull CharSequence message, int duration, boolean withIcon) {
        return custom(context, message, getDrawable(context, com.hww.common.R.drawable.ic_info_outline_white_24dp),
                getColor(context, com.hww.common.R.color.infoColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 显示一个成功提示的Toast
     */
    @CheckResult
    public static Toast success(@NonNull Context context, @StringRes int message) {
        return success(context, context.getString(message), Toast.LENGTH_SHORT, true);
    }

    /**
     * 显示一个成功提示的Toast
     */
    @CheckResult
    public static Toast success(@NonNull Context context, @NonNull CharSequence message) {
        return success(context, message, Toast.LENGTH_SHORT, true);
    }

    /**
     * 显示一个成功提示的Toast
     */
    @CheckResult
    public static Toast success(@NonNull Context context, @StringRes int message, int duration) {
        return success(context, context.getString(message), duration, true);
    }

    /**
     * 显示一个成功提示的Toast
     */
    @CheckResult
    public static Toast success(@NonNull Context context, @NonNull CharSequence message, int duration) {
        return success(context, message, duration, true);
    }

    /**
     * 显示一个成功提示的Toast。
     * <p>
     * 该方法用于在用户界面中显示一个短暂的提示信息，指示某个操作已经成功完成。
     * Toast会显示指定的消息文本，并可选择是否显示一个图标来增强提示信息的可视性。
     * </p>
     *
     * @param context  上下文对象，用于显示Toast。必须不为空。
     * @param message  要显示的提示信息，从资源文件中获取，必须不为空。
     * @param duration Toast显示的时长。可以是{@link Toast#LENGTH_SHORT}或{@link Toast#LENGTH_LONG}之一。
     * @param withIcon 是否在Toast中显示图标。如果为true，则显示一个表示成功的图标。
     * @return 返回创建的Toast对象，可以通过调用其show()方法来显示Toast。
     */
    @CheckResult
    public static Toast success(@NonNull Context context, @StringRes int message, int duration, boolean withIcon) {
        return custom(context, context.getString(message), getDrawable(context, com.hww.common.R.drawable.ic_check_white_24dp),
                getColor(context, com.hww.common.R.color.successColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 显示一个成功提示的Toast。
     * <p>
     * 该方法用于在用户界面中显示一个短暂的提示信息，指示某个操作已经成功完成。
     * Toast会显示指定的消息文本，并可选择是否显示一个图标来增强提示信息的可视性。
     * </p>
     *
     * @param context  上下文对象，用于显示Toast。必须不为空。
     * @param message  要显示的提示信息。必须不为空。
     * @param duration Toast显示的时长。可以是{@link Toast#LENGTH_SHORT}或{@link Toast#LENGTH_LONG}之一。
     * @param withIcon 是否在Toast中显示图标。如果为true，则显示一个表示成功的图标。
     * @return 返回创建的Toast对象，可以通过调用其show()方法来显示Toast。
     */
    @CheckResult
    public static Toast success(@NonNull Context context, @NonNull CharSequence message, int duration, boolean withIcon) {
        return custom(context, message, getDrawable(context, com.hww.common.R.drawable.ic_check_white_24dp),
                getColor(context, com.hww.common.R.color.successColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 创建一个自定义的Toast用于显示错误信息
     */
    @CheckResult
    public static Toast error(@NonNull Context context, @StringRes int message) {
        return error(context, context.getString(message), Toast.LENGTH_SHORT, true);
    }

    /**
     * 创建一个自定义的Toast用于显示错误信息
     */
    @CheckResult
    public static Toast error(@NonNull Context context, @NonNull CharSequence message) {
        return error(context, message, Toast.LENGTH_SHORT, true);
    }

    /**
     * 创建一个自定义的Toast用于显示错误信息
     */
    @CheckResult
    public static Toast error(@NonNull Context context, @StringRes int message, int duration) {
        return error(context, context.getString(message), duration, true);
    }

    /**
     * 创建一个自定义的Toast用于显示错误信息
     */
    @CheckResult
    public static Toast error(@NonNull Context context, @NonNull CharSequence message, int duration) {
        return error(context, message, duration, true);
    }

    /**
     * 创建一个自定义的Toast用于显示错误信息。
     * 此方法为调用者提供了显示错误信息的便捷方式，通过预设的图标和颜色，使错误提示更具视觉效果。
     *
     * @param context  上下文对象，用于创建Toast和获取资源。
     * @param message  要显示的错误信息，从资源文件中获取。
     * @param duration Toast显示的时长，可以是短时长或长时长。
     * @param withIcon 是否在Toast中显示图标。
     * @return 返回创建的Toast对象，调用者可以进一步定制或直接显示。
     */
    @CheckResult
    public static Toast error(@NonNull Context context, @StringRes int message, int duration, boolean withIcon) {
        return custom(context, context.getString(message), getDrawable(context, com.hww.common.R.drawable.ic_clear_white_24dp),
                getColor(context, com.hww.common.R.color.errorColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 创建一个自定义的Toast用于显示错误信息。
     * 此方法为调用者提供了显示错误信息的便捷方式，通过预设的图标和颜色，使错误提示更具视觉效果。
     *
     * @param context  上下文对象，用于创建Toast和获取资源。
     * @param message  要显示的错误信息。
     * @param duration Toast显示的时长，可以是短时长或长时长。
     * @param withIcon 是否在Toast中显示图标。
     * @return 返回创建的Toast对象，调用者可以进一步定制或直接显示。
     */
    @CheckResult
    public static Toast error(@NonNull Context context, @NonNull CharSequence message, int duration, boolean withIcon) {
        return custom(context, message, getDrawable(context, com.hww.common.R.drawable.ic_clear_white_24dp),
                getColor(context, com.hww.common.R.color.errorColor), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, true);
    }

    /**
     * 创建一个自定义的Toast。
     */
    @CheckResult
    public static Toast custom(@NonNull Context context, @StringRes int message, Drawable icon,
                               int duration, boolean withIcon) {
        return custom(context, context.getString(message), icon, -1, getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, false);
    }

    /**
     * 创建一个自定义的Toast。
     */
    @CheckResult
    public static Toast custom(@NonNull Context context, @NonNull CharSequence message, Drawable icon,
                               int duration, boolean withIcon) {
        return custom(context, message, icon, -1, getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, false);
    }

    /**
     * 创建一个自定义的Toast，允许设置图标、背景色、文字颜色等。
     *
     * @param context      上下文对象，用于创建Toast。
     * @param message      要显示的文本消息。
     * @param iconRes      Toast显示的图标资源ID。如果不需要显示图标，可以传入0。
     * @param tintColorRes Toast背景色的资源ID。用于定制Toast的背景颜色。
     * @param duration     Toast显示的持续时间。
     * @param withIcon     是否显示图标。
     * @param shouldTint   是否对图标或背景进行着色。
     * @return 创建的自定义Toast对象。
     */
    @CheckResult
    public static Toast custom(@NonNull Context context, @StringRes int message, @DrawableRes int iconRes,
                               @ColorRes int tintColorRes, int duration,
                               boolean withIcon, boolean shouldTint) {
        return custom(context, context.getString(message), getDrawable(context, iconRes),
                getColor(context, tintColorRes), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, shouldTint);
    }

    /**
     * 创建一个自定义样式的Toast。
     *
     * @param context      Toast显示的上下文环境。
     * @param message      Toast要显示的文本消息。
     * @param iconRes      Toast显示的图标资源ID。如果不需要显示图标，可以传入0。
     * @param tintColorRes Toast背景色的资源ID。用于定制Toast的背景颜色。
     * @param duration     Toast显示的持续时间，可以是短时间（Toast.LENGTH_SHORT）或长时间（Toast.LENGTH_LONG）。
     * @param withIcon     指示是否在Toast中显示图标。
     * @param shouldTint   指示是否对图标进行着色处理。
     * @return 返回一个具有自定义样式的Toast实例。
     */
    @CheckResult
    public static Toast custom(@NonNull Context context, @NonNull CharSequence message, @DrawableRes int iconRes,
                               @ColorRes int tintColorRes, int duration,
                               boolean withIcon, boolean shouldTint) {
        return custom(context, message, getDrawable(context, iconRes),
                getColor(context, tintColorRes), getColor(context, com.hww.common.R.color.defaultTextColor),
                duration, withIcon, shouldTint);
    }

    /**
     * 创建一个自定义的Toast，允许设置图标、背景色、文字颜色等。
     *
     * @param context      上下文对象，用于创建Toast。
     * @param message      要显示的文本消息。
     * @param icon         Toast显示的图标。
     * @param tintColorRes Toast背景色的资源id。
     * @param duration     Toast显示的持续时间。
     * @param withIcon     是否显示图标。
     * @param shouldTint   是否对图标或背景进行着色。
     * @return 创建的自定义Toast对象。
     */
    @CheckResult
    public static Toast custom(@NonNull Context context, @StringRes int message, Drawable icon,
                               @ColorRes int tintColorRes, int duration,
                               boolean withIcon, boolean shouldTint) {
        return custom(context, context.getString(message), icon, getColor(context, tintColorRes),
                getColor(context, com.hww.common.R.color.defaultTextColor), duration, withIcon, shouldTint);
    }

    /**
     * 创建一个自定义样式的Toast。
     * <p>
     * 该方法提供了一种灵活的方式来创建具有自定义图标、背景色、文字颜色等的Toast。通过传入不同的资源id和参数，
     * 可以定制Toast的显示样式。特别地，可以通过shouldTint参数来控制是否对图标进行着色，以适配不同的主题需求。
     *
     * @param context      Toast显示的上下文环境。
     * @param message      Toast显示的文本内容。
     * @param icon         Toast显示的图标，可以为null表示不显示图标。
     * @param tintColorRes Toast背景色的资源id。
     * @param textColorRes Toast文字颜色的资源id。
     * @param duration     Toast显示的时长，可以是Toast.LENGTH_SHORT或Toast.LENGTH_LONG。
     * @param withIcon     指示是否在Toast中显示图标。
     * @param shouldTint   指示是否对图标进行着色。
     * @return 返回创建的自定义样式的Toast对象。
     */
    @CheckResult
    public static Toast custom(@NonNull Context context, @StringRes int message, Drawable icon,
                               @ColorRes int tintColorRes, @ColorRes int textColorRes, int duration,
                               boolean withIcon, boolean shouldTint) {
        return custom(context, context.getString(message), icon, getColor(context, tintColorRes),
                getColor(context, textColorRes), duration, withIcon, shouldTint);
    }


    /**
     * 创建一个自定义的Toast，允许设置图标、背景色、文字颜色等。
     *
     * @param context    上下文对象，用于创建Toast。
     * @param message    要显示的文本消息。
     * @param icon       Toast显示的图标。
     * @param tintColor  图标或背景的着色颜色。
     * @param textColor  文本的颜色。
     * @param duration   Toast显示的持续时间。
     * @param withIcon   是否显示图标。
     * @param shouldTint 是否对图标或背景进行着色。
     * @return 创建的自定义Toast对象。
     */
    @SuppressLint("ShowToast")
    @CheckResult
    public static Toast custom(@NonNull Context context, @NonNull CharSequence message, Drawable icon,
                               @ColorInt int tintColor, @ColorInt int textColor, int duration,
                               boolean withIcon, boolean shouldTint) {
        final Toast currentToast = Toast.makeText(context, "", duration);
        /*加载自定义的Toast布局*/
        final View toastLayout = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
                .inflate(com.hww.common.R.layout.toast_layout, null);
        final LinearLayout toastRoot = toastLayout.findViewById(com.hww.common.R.id.toast_root);
        final ImageView toastIcon = toastLayout.findViewById(com.hww.common.R.id.toast_icon);
        final TextView toastTextView = toastLayout.findViewById(com.hww.common.R.id.toast_text);
        Drawable drawableFrame;

        if (shouldTint)
            drawableFrame = tint9PatchDrawableFrame(context, tintColor);
        else
            drawableFrame = getDrawable(context, com.hww.common.R.drawable.toast_frame);
        setBackground(toastLayout, drawableFrame);

        if (withIcon) {
            if (icon == null)
                throw new IllegalArgumentException("Avoid passing 'icon' as null if 'withIcon' is set to true");
            if (isRTL && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
                toastRoot.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
            setBackground(toastIcon, tintIcon ? tintIcon(icon, textColor) : icon);
        } else {
            toastIcon.setVisibility(View.GONE);
        }

        toastTextView.setText(message);
        toastTextView.setTextColor(textColor);
        toastTextView.setTypeface(currentTypeface);
        toastTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);

        currentToast.setView(toastLayout);

        if (!allowQueue) {
            if (lastToast != null)
                lastToast.cancel();
            lastToast = currentToast;
        }

        // Make sure to use default values for non-specified ones.
        currentToast.setGravity(
                toastGravity == -1 ? currentToast.getGravity() : toastGravity,
                xOffset == -1 ? currentToast.getXOffset() : xOffset,
                yOffset == -1 ? currentToast.getYOffset() : yOffset
        );

        return currentToast;
    }

    /**
     * 根据当前主题模式（暗黑模式或明亮模式）创建并返回一个Toast对象。
     * 该方法首先检查是否支持暗黑模式以及当前的UI模式，然后根据这些信息决定是创建一个明亮主题还是暗黑主题的Toast。
     * 对于Android Q（API级别29）及更高版本，如果支持暗黑模式且当前UI模式为暗黑模式，则创建暗黑主题的Toast；
     * 否则，创建明亮主题的Toast。对于Android O MR1（API级别27）到Android Q之间的版本，默认创建明亮主题的Toast；
     * 对于Android O MR1之前的版本，默认创建暗黑主题的Toast。
     *
     * @param context  上下文对象，用于创建Toast。
     * @param message  Toast显示的文本消息。
     * @param icon     Toast显示的图标。
     * @param duration Toast显示的持续时间，可以是短时间（Toast.LENGTH_SHORT）或长时间（Toast.LENGTH_LONG）。
     * @param withIcon 指示Toast是否应该显示图标的布尔值。
     * @return 创建的Toast对象。
     */
    private static Toast normalWithDarkThemeSupport(@NonNull Context context, @NonNull CharSequence message, Drawable icon,
                                                    int duration, boolean withIcon) {
        if (supportDarkTheme && Build.VERSION.SDK_INT >= 29) {
            int uiMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
            if (uiMode == Configuration.UI_MODE_NIGHT_NO) {
                return withLightTheme(context, message, icon, duration, withIcon);
            }
            return withDarkTheme(context, message, icon, duration, withIcon);
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                return withLightTheme(context, message, icon, duration, withIcon);
            } else {
                return withDarkTheme(context, message, icon, duration, withIcon);
            }
        }
    }

    /**
     * 创建一个具有明亮主题的Toast对象。
     * 该方法通过定制Toast的显示样式，包括消息文本、图标、背景色和文本颜色等，来创建一个符合明亮主题的Toast。
     * 主要用于在应用程序中提供一种统一且易于阅读的提示信息展示方式。
     *
     * @param context  上下文对象，用于获取资源和进行UI绘制。
     * @param message  提示信息的内容。
     * @param icon     Toast显示时伴随的图标，用于增强信息的可识别性或表达情感。
     * @param duration Toast显示的时长，可以是短时长或长时长。
     * @param withIcon 指示是否在Toast中显示图标的标志位。
     * @return 创建的具有明亮主题的Toast对象。
     */
    private static Toast withLightTheme(@NonNull Context context, @NonNull CharSequence message, Drawable icon,
                                        int duration, boolean withIcon) {
        return custom(context, message, icon, getColor(context, com.hww.common.R.color.defaultTextColor),
                getColor(context, com.hww.common.R.color.normalColor), duration, withIcon, true);
    }

    /**
     * 创建一个具有暗黑主题的Toast对象。
     * 此方法通过定制Toast的外观，包括消息文本和图标，来创建一个符合暗黑主题风格的Toast。
     * 主要用于在应用程序中提供一致的UI反馈。
     *
     * @param context  上下文对象，用于获取资源和进行UI渲染。
     * @param message  Toast显示的文本消息。
     * @param icon     Toast显示的图标，可以为null表示不显示图标。
     * @param duration Toast显示的持续时间，可以是短时间（Toast.LENGTH_SHORT）或长时间（Toast.LENGTH_LONG）。
     * @param withIcon 指示是否在Toast中显示图标的布尔值。
     * @return 返回定制后的Toast对象。
     */
    private static Toast withDarkTheme(@NonNull Context context, @NonNull CharSequence message, Drawable icon,
                                       int duration, boolean withIcon) {
        return custom(context, message, icon, getColor(context, com.hww.common.R.color.normalColor),
                getColor(context, com.hww.common.R.color.defaultTextColor), duration, withIcon, true);
    }

    public static class Config {
        /*默认字体类型*/
        private Typeface typeface = ToastUtils.currentTypeface;
        /*文本大小(单位：sp)*/
        private int textSize = ToastUtils.textSize;
        /*是否允许图标着色*/
        private boolean tintIcon = ToastUtils.tintIcon;
        /*是否允许队列显示(多条Toast消息)*/
        private boolean allowQueue = true;
        /*Toast消息的重力位置(屏幕定位)*/
        private int toastGravity = ToastUtils.toastGravity;
        /*X轴偏移量(单位：px)*/
        private int xOffset = ToastUtils.xOffset;
        /*Y轴偏移量(单位：px)*/
        private int yOffset = ToastUtils.yOffset;
        /*是否支持深色主题*/
        private boolean supportDarkTheme = true;
        /*是否为镜像显示，由右到左显示语言环境(如阿拉伯语、希腊语)*/
        private boolean isRTL = false;

        private Config() {
            // avoiding instantiation
        }

        @CheckResult
        public static Config getInstance() {
            return new Config();
        }

        /**
         * 重置配置
         */
        public static void reset() {
            ToastUtils.currentTypeface = LOADED_TOAST_TYPEFACE;
            ToastUtils.textSize = 16;
            ToastUtils.tintIcon = true;
            ToastUtils.allowQueue = true;
            ToastUtils.toastGravity = -1;
            ToastUtils.xOffset = -1;
            ToastUtils.yOffset = -1;
            ToastUtils.supportDarkTheme = true;
            ToastUtils.isRTL = false;
        }

        @CheckResult
        public Config setToastTypeface(@NonNull Typeface typeface) {
            this.typeface = typeface;
            return this;
        }

        @CheckResult
        public Config setTextSize(int sizeInSp) {
            this.textSize = sizeInSp;
            return this;
        }

        @CheckResult
        public Config tintIcon(boolean tintIcon) {
            this.tintIcon = tintIcon;
            return this;
        }

        @CheckResult
        public Config allowQueue(boolean allowQueue) {
            this.allowQueue = allowQueue;
            return this;
        }

        @CheckResult
        public Config setGravity(int gravity, int xOffset, int yOffset) {
            this.toastGravity = gravity;
            this.xOffset = xOffset;
            this.yOffset = yOffset;
            return this;
        }

        @CheckResult
        public Config setGravity(int gravity) {
            this.toastGravity = gravity;
            return this;
        }

        @CheckResult
        public Config supportDarkTheme(boolean supportDarkTheme) {
            this.supportDarkTheme = supportDarkTheme;
            return this;
        }

        public Config setRTL(boolean isRTL) {
            this.isRTL = isRTL;
            return this;
        }

        /**
         * 应用当前配置
         */
        public void apply() {
            ToastUtils.currentTypeface = typeface;
            ToastUtils.textSize = textSize;
            ToastUtils.tintIcon = tintIcon;
            ToastUtils.allowQueue = allowQueue;
            ToastUtils.toastGravity = toastGravity;
            ToastUtils.xOffset = xOffset;
            ToastUtils.yOffset = yOffset;
            ToastUtils.supportDarkTheme = supportDarkTheme;
            ToastUtils.isRTL = isRTL;
        }
    }

    /**
     * 为Drawable图标着色
     *
     * @param drawable  要着色的Drawable对象，不能为空
     * @param tintColor 要应用的颜色值，必须为有效的颜色整型值
     * @return 着色后的Drawable对象
     */
    public static Drawable tintIcon(@NonNull Drawable drawable, @ColorInt int tintColor) {
        /*使用PorterDuff.Mode.SRC_IN模式设置颜色过滤器，实现图标的着色*/
        drawable.setColorFilter(tintColor, PorterDuff.Mode.SRC_IN);
        return drawable;
    }

    /**
     * 对toast_frame九宫格图形进行着色处理。
     * 该方法通过获取预定义的toast_frame图形资源，并将其颜色更改为指定的tintColor，
     * 最后返回着色后的NinePatchDrawable对象。
     *
     * @param context   上下文对象，用于获取资源。
     * @param tintColor 指定的颜色值，用于给toast_frame图形着色。
     * @return 着色后的NinePatchDrawable对象。
     */
    public static Drawable tint9PatchDrawableFrame(@NonNull Context context, @ColorInt int tintColor) {
        final NinePatchDrawable toastDrawable = (NinePatchDrawable) getDrawable(context, com.hww.common.R.drawable.toast_frame);
        return tintIcon(toastDrawable, tintColor);
    }

    /**
     * 设置视图的背景。根据Android版本的不同，使用不同的方法来设置背景。
     * 从Android 4.1（JELLY_BEAN）开始，推荐使用setBackground方法，对于早期版本，则使用setBackgroundDrawable方法。
     *
     * @param view     需要设置背景的视图。
     * @param drawable 要设置为视图背景的Drawable对象。
     */
    public static void setBackground(@NonNull View view, Drawable drawable) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
            view.setBackground(drawable);
        else
            view.setBackgroundDrawable(drawable);
    }

    /**
     * 根据资源ID获取Drawable对象。
     * <p>
     * 该方法通过AppCompatResources从给定的上下文中获取指定资源ID的Drawable对象。使用此方法可以确保在不同版本的Android系统中都能兼容地获取Drawable资源。
     * 主要用于在需要使用Drawable的地方，通过资源ID来动态获取Drawable对象。
     *
     * @param context 上下文对象，用于获取资源。不能为空。
     * @param id      要获取的Drawable资源的ID。必须是一个有效的资源ID。
     * @return 返回指定资源ID的Drawable对象。如果无法获取资源或资源ID无效，则返回null。
     */
    public static Drawable getDrawable(@NonNull Context context, @DrawableRes int id) {
        return AppCompatResources.getDrawable(context, id);
    }

    /**
     * 获取指定资源ID的颜色值。
     * <p>
     * 此方法封装了ContextCompat.getColor方法的调用，提供了对颜色资源的访问。
     * 它的存在使得可以在不直接依赖特定API级别的情况下获取颜色资源，
     * 从而提高了代码的兼容性。
     *
     * @param context 上下文对象，用于访问资源。
     * @param color   要获取的颜色资源的ID。必须是一个有效的资源ID。
     * @return 返回指定资源ID的颜色值。
     */
    public static int getColor(@NonNull Context context, @ColorRes int color) {
        return ContextCompat.getColor(context, color);
    }
}
